<!-- 登录页面 童晓白 2025-07-27 -->
<template>
  <view class="background">
    <!-- 简单渐变背景和浮动圆形 -->
    <view class="floating-shapes">
      <view class="shape" style="width: 220rpx; height: 220rpx; top: 10%; left: 5%"></view>
      <view class="shape" style="width: 150rpx; height: 150rpx; top: 60%; left: 80%"></view>
      <view class="shape" style="width: 180rpx; height: 180rpx; top: 30%; left: 70%"></view>
    </view>
  </view>
  <view class="container">
    <view class="login-card">
      <view class="title">用户登录</view>
      <view v-if="errorMessage" class="error-message">{{ errorMessage }}</view>
      <view v-if="loggedInMessage" class="success-message">{{ loggedInMessage }}</view>

      <!-- 登录类型选择 -->
      <view class="form-group">
        <label>登录类型</label>
        <picker :range="loginTypeOptions" :value="loginTypeIndex" @change="onLoginTypePickerChange">
          <view class="uni-input">{{ loginTypeOptions[loginTypeIndex] }}</view>
        </picker>
      </view>

      <view class="form-group">
        <label>个人账户 (手机号/邮箱/UID)</label>
        <input v-model="identifier" placeholder="请输入您的账户" />
      </view>

      <!-- 密码登录 -->
      <view class="form-group" v-if="loginType === 'password'">
        <label>密码</label>
        <input type="password" v-model="password" placeholder="请输入密码" />
      </view>

      <!-- 验证码登录 -->
      <view class="form-group" v-if="loginType === 'code'">
        <label>验证码</label>
        <view class="code-group">
          <input v-model="code" placeholder="请输入验证码" />
          <button 
            class="send-code-btn" 
            @click="sendCode" 
            :disabled="isCodeSending || !identifier"
          >
            {{ codeBtnText }}
          </button>
        </view>
      </view>

      <!-- 人脸识别登录 -->
      <view class="form-group" v-if="loginType === 'face'">
        <label>人脸识别</label>
        <view class="face-recognition">
          <view v-if="currentAction" class="action-prompt">
            <view class="action-icon" :class="currentAction">
              <text v-if="currentAction === 'shake_head'">摇头</text>
              <text v-else-if="currentAction === 'open_mouth'">张嘴</text>
              <text v-else-if="currentAction === 'blink_eye'">眨眼</text>
            </view>
            <text>{{ actionDescription }}</text>
            <text class="recording-status" v-if="isRecording">
              正在录制... {{ recordingTime }}s
            </text>
          </view>
          
          <!-- H5端视频容器 -->
          <!-- #ifdef H5 -->
          <div id="video-container" class="video-container" v-if="isCameraActive"></div>
          <!-- #endif -->
          
          <!-- 微信小程序端摄像头 -->
          <!-- #ifdef APP-PLUS || MP-WEIXIN -->
          <camera
            v-if="isCameraActive"
            device-position="front"
            flash="off"
            style="width: 100%; height: 300rpx;"
            @error="onCameraError"
          ></camera>
          <!-- #endif -->
          
          <view class="face-buttons">
            <button type="button" @click="toggleCamera">{{ isCameraActive ? '关闭摄像头' : '开启摄像头' }}</button>
            <button type="button" @click="startRecording" :disabled="!isCameraActive || isRecording">开始录制</button>
            <button type="button" @click="getNewAction" :disabled="!isCameraActive">更换动作</button>
          </view>
          <view v-if="recordedFrames.length > 0" class="recording-preview">
            <text>已录制 {{ recordedFrames.length }} 帧</text>
          </view>
        </view>
      </view>

      <button class="login-btn" @click="login" :disabled="loginBtnLoading">登录</button>

      <view class="links">
        <text @click="goToRegister">创建账户</text> |
        <text @click="goToForgetPassword">忘记密码?</text>
      </view>
    </view>
  </view>
</template>

<script setup>
import { NETWORK_CONFIG } from '@/config/network.js'
import { ref, onUnmounted, watch, onMounted } from "vue";
import { useUserStore } from '@/store/user'

const userStore = useUserStore();

// 表单数据
const loginType = ref("password");
const identifier = ref("");
const password = ref("");
const code = ref("");

// 设备信息
const deviceInfo = ref({
  deviceId: '',
  deviceName: '',
  deviceType: '',
  deviceBrand: '',
  deviceModel: '',
  deviceToken: '',
  appVersion: '',
  osVersion: ''
});

// 消息
const errorMessage = ref("");
const loggedInMessage = ref("");

// 人脸识别相关
const isCameraActive = ref(false);
const currentAction = ref('');
const actionDescription = ref('');
const isRecording = ref(false);
const recordingTime = ref(0);
const recordedFrames = ref([]);
const recordingInterval = ref(null);
const frameCaptureInterval = ref(null);

// H5摄像头相关
const videoElement = ref(null);
const stream = ref(null);

// 登录按钮 loading 状态
const loginBtnLoading = ref(false);

// 验证码相关
const isCodeSending = ref(false);
const codeBtnText = ref("发送验证码");
let codeTimer = null;

// 登录类型选项
const loginTypeOptions = ['密码登录', '验证码登录', '人脸识别登录'];
const loginTypeIndex = ref(0);

// 获取设备信息
const getDeviceInfo = () => {
  try {
    // 获取系统信息
    const systemInfo = uni.getSystemInfoSync();
    
    // 生成设备ID（使用设备唯一标识）
    const deviceId = systemInfo.deviceId || systemInfo.imei || 
                    (systemInfo.platform + '_' + systemInfo.model + '_' + Date.now());
    
    // 获取设备品牌
    let deviceBrand = 'unknown';
    if (systemInfo.brand) {
      deviceBrand = systemInfo.brand.toLowerCase();
    } else if (systemInfo.platform === 'ios') {
      deviceBrand = 'apple';
    } else if (systemInfo.platform === 'android') {
      deviceBrand = 'android';
    }
    
    // 生成设备名称
    let deviceName = '';
    if (systemInfo.brand && systemInfo.model) {
      deviceName = `${systemInfo.brand} ${systemInfo.model}`;
    } else if (systemInfo.model) {
      deviceName = systemInfo.model;
    } else {
      deviceName = `${systemInfo.platform} 设备`;
    }
    
    deviceInfo.value = {
      deviceId: deviceId,
      deviceName: deviceName,
      deviceType: systemInfo.platform || 'unknown',
      deviceBrand: deviceBrand,
      deviceModel: systemInfo.model || 'unknown',
      deviceToken: '', // 推送Token，需要单独获取
      appVersion: systemInfo.version || '1.0.0',
      osVersion: systemInfo.system || 'unknown'
    };
    
    console.log('设备信息获取成功:', deviceInfo.value);
  } catch (error) {
    console.error('获取设备信息失败:', error);
    // 设置默认值
    deviceInfo.value = {
      deviceId: 'device_' + Date.now(),
      deviceName: '未知设备',
      deviceType: 'unknown',
      deviceBrand: 'unknown',
      deviceModel: 'unknown',
      deviceToken: '',
      appVersion: '1.0.0',
      osVersion: 'unknown'
    };
  }
};

// picker 选择事件
function onLoginTypePickerChange(e) {
  loginTypeIndex.value = e.detail.value;
  if (loginTypeIndex.value == 0) loginType.value = 'password';
  else if (loginTypeIndex.value == 1) loginType.value = 'code';
  else if (loginTypeIndex.value == 2) loginType.value = 'face';
  handleLoginTypeChange();
}

// 保证loginType变化时同步picker索引
watch(loginType, (val) => {
  if (val === 'password') loginTypeIndex.value = 0;
  else if (val === 'code') loginTypeIndex.value = 1;
  else if (val === 'face') loginTypeIndex.value = 2;
});

// 登录类型切换
const handleLoginTypeChange = () => {
  errorMessage.value = "";
};

// 发送验证码
const sendCode = async () => {
  if (!identifier.value) {
    uni.showToast({
      title: '请输入您的手机号或邮箱',
      icon: 'none'
    });
    return;
  }

  try {
    isCodeSending.value = true;
    codeBtnText.value = "发送中...";
    
    const res = await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/auth/send-code`,
      method: "POST",
      header: { "Content-Type": "application/json" },
      data: { identifier: identifier.value },
    });
    
    if (res.statusCode === 200) {
      errorMessage.value = "验证码已发送，请查收";
      
      uni.showToast({
        title: '验证码已发送，五分钟内有效',
        icon: 'success'
      });
      
      // 倒计时
      let countdown = 60;
      codeBtnText.value = `已发送(${countdown}s)`;
      
      if (codeTimer) clearInterval(codeTimer);
      
      codeTimer = setInterval(() => {
        countdown--;
        codeBtnText.value = `已发送(${countdown}s)`;
        
        if (countdown <= 0) {
          clearInterval(codeTimer);
          codeBtnText.value = "发送验证码";
          isCodeSending.value = false;
        }
      }, 1000);
    } else {
      errorMessage.value = (res.data && res.data.message) || "发送验证码失败";
      isCodeSending.value = false;
      codeBtnText.value = "发送验证码";
      
      uni.showToast({
        title: (res.data && res.data.message) || '发送验证码失败',
        icon: 'none'
      });
    }
  } catch (error) {
    errorMessage.value = "发送验证码时出错: " + error.message;
    isCodeSending.value = false;
    codeBtnText.value = "发送验证码";
    
    uni.showToast({
      title: '发送验证码失败',
      icon: 'none'
    });
  }
};

// 摄像头相关
const toggleCamera = async () => {
  if (isCameraActive.value) {
    stopCamera();
  } else {
    await startCamera();
  }
};

// 启动摄像头
const startCamera = async () => {
  try {
    // #ifdef H5
    const video = document.createElement('video');
    video.autoplay = true;
    video.playsInline = true;
    video.style.width = '100%';
    video.style.height = '300px';
    video.style.borderRadius = '12px';
    
    const container = document.querySelector('.face-recognition');
    if (container) {
      container.appendChild(video);
      videoElement.value = video;
    }
    
    const mediaStream = await navigator.mediaDevices.getUserMedia({ 
      video: { 
        facingMode: 'user',
        width: { ideal: 640 },
        height: { ideal: 480 }
      } 
    });
    video.srcObject = mediaStream;
    stream.value = mediaStream;
    isCameraActive.value = true;
    // #endif
    
    // #ifdef APP-PLUS || MP-WEIXIN
    isCameraActive.value = true;
    // #endif
  } catch (error) {
    console.error('摄像头访问失败:', error);
    uni.showToast({
      title: '摄像头权限被拒绝或设备不支持',
      icon: 'none'
    });
    isCameraActive.value = false;
  }
};

// 停止摄像头
const stopCamera = () => {
  // #ifdef H5
  if (stream.value) {
    stream.value.getTracks().forEach(track => track.stop());
    stream.value = null;
  }
  if (videoElement.value) {
    videoElement.value.remove();
    videoElement.value = null;
  }
  // #endif
  isCameraActive.value = false;
};

const onCameraError = (e) => {
  uni.showToast({ title: '摄像头错误', icon: 'none' });
  isCameraActive.value = false;
};

const startRecording = () => {
  if (!isCameraActive.value) return;
  isRecording.value = true;
  recordingTime.value = 0;
  recordedFrames.value = [];
  
  // 录制时间计时
  recordingInterval.value = setInterval(() => {
    recordingTime.value++;
    if (recordingTime.value >= 3) {
      stopRecording();
    }
  }, 1000);
  
  // 真实帧采集
  frameCaptureInterval.value = setInterval(() => {
    captureFrame();
  }, 200);
};

// 采集帧数据
const captureFrame = () => {
  console.log('开始采集帧数据...');
  // #ifdef H5
  if (videoElement.value) {
    const video = videoElement.value;
    console.log('视频元素存在，视频尺寸:', video.videoWidth, 'x', video.videoHeight);
    if (video.videoWidth && video.videoHeight) {
      const canvas = document.createElement('canvas');
      const context = canvas.getContext('2d');
      if (context) {
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
        const base64 = canvas.toDataURL('image/jpeg', 0.8);
        console.log('采集到真实base64数据，长度:', base64.length);
        recordedFrames.value.push(base64);
      } else {
        console.error('无法创建canvas上下文');
      }
    } else {
      console.warn('视频尺寸无效');
    }
  } else {
    console.warn('视频元素不存在');
  }
  // #endif
  
  // #ifdef APP-PLUS || MP-WEIXIN
  const cameraContext = uni.createCameraContext();
  if (cameraContext) {
    cameraContext.takePhoto({
      quality: 'high',
      success: (res) => {
        // 将图片路径转换为base64
        uni.getFileSystemManager().readFile({
          filePath: res.tempImagePath,
          encoding: 'base64',
          success: (fileRes) => {
            const base64 = 'data:image/jpeg;base64,' + fileRes.data;
            recordedFrames.value.push(base64);
          },
          fail: (err) => {
            console.error('读取图片失败:', err);
          }
        });
      },
      fail: (err) => {
        console.error('拍照失败:', err);
      }
    });
  }
  // #endif
};

const stopRecording = () => {
  isRecording.value = false;
  clearInterval(recordingInterval.value);
  clearInterval(frameCaptureInterval.value);
  if (recordedFrames.value.length < 5) {
    uni.showToast({
      title: '录制时间太短，请重试',
      icon: 'none'
    });
    recordedFrames.value = [];
    return;
  }
};

onUnmounted(() => {
  if (recordingInterval.value) clearInterval(recordingInterval.value);
  if (frameCaptureInterval.value) clearInterval(frameCaptureInterval.value);
  if (codeTimer) clearInterval(codeTimer);
  stopCamera();
});

// 获取新的动作要求
const getNewAction = async () => {
  try {
    const res = await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/auth/login/face/action`,
      method: "GET"
    });
    if (res.statusCode === 200) {
      const data = res.data;
      currentAction.value = data.action;
      actionDescription.value = data.description;
    } else {
      errorMessage.value = (res.data && res.data.message) || "获取动作要求失败";
    }
  } catch (error) {
    errorMessage.value = "获取动作要求失败: " + error.message;
  }
};

const login = async () => {
  if (!identifier.value || 
      (loginType.value === "password" && !password.value) || 
      (loginType.value === "code" && !code.value) ||
      (loginType.value === "face" && (recordedFrames.value.length === 0 || !currentAction.value))) {
    errorMessage.value = "请填写所有必填字段。";
    return;
  }
  loginBtnLoading.value = true;
  
  // 调试信息
  if (loginType.value === "face") {
    console.log('人脸登录调试信息:');
    console.log('录制的帧数:', recordedFrames.value.length);
    console.log('第一帧数据预览:', recordedFrames.value[0] ? recordedFrames.value[0].substring(0, 50) + '...' : '无数据');
    console.log('当前动作:', currentAction.value);
  }
  
  const loginRequest = {
    loginType: loginType.value,
    identifier: identifier.value,
    password: loginType.value === "password" ? password.value : undefined,
    code: loginType.value === "code" ? code.value : undefined,
    frames: loginType.value === "face" ? recordedFrames.value : undefined,
    action: loginType.value === "face" ? currentAction.value : undefined,
    // 添加设备信息
    deviceId: deviceInfo.value.deviceId,
    deviceName: deviceInfo.value.deviceName,
    deviceType: deviceInfo.value.deviceType,
    deviceBrand: deviceInfo.value.deviceBrand,
    deviceModel: deviceInfo.value.deviceModel,
    deviceToken: deviceInfo.value.deviceToken,
    appVersion: deviceInfo.value.appVersion,
    osVersion: deviceInfo.value.osVersion
  };
  try {
    const res = await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/auth/login`,
      method: "POST",
      header: { 
        "Content-Type": "application/json",
        "Accept": "application/json"
      },
      data: loginRequest,
    });
    if (res.statusCode !== 200) {
      errorMessage.value = (res.data && res.data.message) || "登录失败";
    } else {
      const data = res.data;
      console.log("登录成功，返回数据:", data);
      
      // 确保accessToken字段存在
      if (data && data.accessToken) {
        // 保存到storage
        uni.setStorageSync("accessToken", data.accessToken);
        // 同时设置到store
        userStore.setToken(data.accessToken);
        
        loggedInMessage.value = "登录成功！正在跳转...";
        
        // 立即尝试获取用户信息
        try {
          await userStore.fetchUserProfile();
          console.log("用户配置获取成功:", userStore.profile);
        } catch (profileError) {
          console.error("获取用户配置失败，但继续跳转:", profileError);
          // 即使获取失败也继续，使用默认值
        }
        
        // 重新建立WebSocket连接
        try {
          console.log("登录成功，重新建立WebSocket连接...");
          // 调用全局的WebSocket连接函数
          if (typeof uni !== 'undefined' && uni.connectWebSocket) {
            uni.connectWebSocket();
            console.log("WebSocket连接已重新建立");
          } else {
            console.log("WebSocket连接函数不可用，将在应用启动时建立");
          }
        } catch (wsError) {
          console.error("重新建立WebSocket连接失败:", wsError);
        }
        
        // 延迟跳转确保有足够时间处理
        setTimeout(() => {
          uni.switchTab({
            url: '/pages/index/index'
          });
        }, 2000);
      } else {
        errorMessage.value = "登录成功但未返回有效令牌";
        console.error("登录成功但未返回有效令牌:", data);
      }
    }
  } catch (error) {
    errorMessage.value = "错误: " + error.message;
  } finally {
    loginBtnLoading.value = false;
  }
};

// 跳转注册/忘记密码
const goToRegister = () => {
  uni.navigateTo({
    url: '/pages/register/index'
  });
};
const goToForgetPassword = () => {
  uni.navigateTo({
    url: '/pages/forget-password/index'
  });
};

// 监听登录类型变化
watch(loginType, (newType) => {
  if (newType === 'face') {
    getNewAction();
  }
});

// 页面加载时获取设备信息
onMounted(() => {
  getDeviceInfo();
});
</script>

<style scoped>
/* 背景和浮动圆形 */
.background {
  position: fixed;
  top: 0; left: 0; width: 100vw; height: 100vh;
  background: #4a90e2;
  z-index: 0;
  overflow: hidden;
}
.floating-shapes {
  position: absolute;
  top: 0; left: 0; width: 100vw; height: 100vh;
  pointer-events: none;
  z-index: 1;
}
.shape {
  position: absolute;
  border-radius: 50%;
  background: rgba(255,255,255,0.12);
  filter: blur(8px);
}

/* 容器和卡片 */
.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 2;
  position: relative;
}
.login-card {
  width: 100%;
  max-width: 600rpx; /* 扩大卡片宽度，原480rpx */
  background: #fff;
  border-radius: 24rpx; /* 稍微加大圆角 */
  box-shadow: 0 12rpx 40rpx rgba(0,0,0,0.10); /* 阴影加深 */
  padding: 56rpx 36rpx; /* 增加内边距 */
  display: flex;
  flex-direction: column;
  gap: 28rpx; /* 增大间距 */
  border: 1rpx solid #e0e0e0;
}

/* 标题 */
.title {
  font-size: 48rpx; /* 更大 */
  font-weight: 700;
  color: #1a1a1a;
  margin-bottom: 24rpx;
  text-align: center;
  letter-spacing: -1rpx;
}

/* 登录类型选择优化样式 */
.form-group {
  display: flex;
  flex-direction: column;
  gap: 12rpx;
  margin-bottom: 20rpx;
}
.form-group label {
  font-size: 30rpx;
  color: #4a5568;
  font-weight: 600;
  margin-bottom: 8rpx;
}
/* 登录类型选择卡片感 */
.uni-input {
  background: #f5f8ff;
  border: 2rpx solid #b3c6f7;
  border-radius: 14rpx;
  padding: 28rpx 24rpx;
  font-size: 30rpx;
  font-weight: 600;
  color: #2a3a5a;
  box-shadow: 0 2rpx 8rpx rgba(67, 97, 238, 0.04);
  margin-bottom: 0;
  margin-top: 0;
  transition: border 0.2s;
}
.uni-input:active, .uni-input:focus {
  border: 2rpx solid #4f8cff;
}

input, picker, .uni-input {
  padding: 28rpx 24rpx;
  border: 2rpx solid #e2e8f0;
  border-radius: 12rpx;
  font-size: 28rpx;
  outline: none;
  background: #f8fafc;
  font-family: inherit;
}
input:focus, picker:focus {
  border: 2rpx solid #4f8cff;
  background: #fff;
}

/* 验证码组 */
.code-group {
  display: flex;
  gap: 10rpx;
  align-items: stretch;
}
.code-group input {
  flex: 1;
}
.send-code-btn {
  padding: 24rpx 32rpx;
  background: #4f8cff;
  color: #fff;
  border: none;
  border-radius: 12rpx;
  font-size: 26rpx;
  font-weight: 600;
  cursor: pointer;
  min-width: 120rpx;
}

/* 登录按钮 */
.login-btn {
  width: 100%;
  padding: 32rpx 0;
  background: #4f8cff;
  color: #fff;
  border: none;
  border-radius: 12rpx;
  font-size: 32rpx;
  font-weight: 700;
  cursor: pointer;
  margin-top: 20rpx;
}
.login-btn:disabled {
  background: #cbd5e1;
  cursor: not-allowed;
}

/* 链接 */
.links {
  text-align: center;
  margin-top: 24rpx;
  font-size: 26rpx;
  line-height: 1.5;
}
.links text {
  color: #4f8cff;
  text-decoration: none;
  margin: 0 8rpx;
  cursor: pointer;
  font-weight: 500;
  padding: 4rpx 8rpx;
  border-radius: 6rpx;
}

/* 消息提示 */
.error-message {
  background: #fef2f2;
  color: #dc2626;
  border-radius: 12rpx;
  padding: 20rpx 16rpx;
  font-size: 26rpx;
  text-align: center;
  border: 1rpx solid #fecaca;
  font-weight: 500;
}
.success-message {
  background: #f0fdf4;
  color: #16a34a;
  border-radius: 12rpx;
  padding: 20rpx 16rpx;
  font-size: 26rpx;
  text-align: center;
  border: 1rpx solid #bbf7d0;
  font-weight: 500;
}

/* 人脸识别 */
.face-recognition {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
  align-items: center;
}
.video-container {
  width: 100%;
  height: 300rpx;
  border-radius: 12rpx;
  overflow: hidden;
  background: #f0f0f0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.face-buttons {
  display: flex;
  gap: 12rpx;
  justify-content: center;
  margin-top: 12rpx;
  flex-wrap: wrap;
}
.face-buttons button {
  padding: 18rpx 24rpx;
  background: #4f8cff;
  color: #fff;
  border: none;
  border-radius: 10rpx;
  font-size: 26rpx;
  font-weight: 600;
  cursor: pointer;
  min-width: 80rpx;
}
.face-buttons button:disabled {
  background: #cbd5e1;
  cursor: not-allowed;
}
.action-prompt {
  text-align: center;
  margin-bottom: 12rpx;
  padding: 12rpx;
  background: #e8f0fe;
  border-radius: 12rpx;
}
.action-icon {
  font-size: 32rpx;
  margin-bottom: 8rpx;
  color: #4f8cff;
}
.recording-status {
  color: #dc2626;
  font-weight: bold;
  margin-top: 8rpx;
}
.recording-preview {
  margin-top: 12rpx;
  padding: 8rpx;
  background: #e8f0fe;
  border-radius: 12rpx;
  text-align: center;
}
</style>